#include "PCArithOp.h"

#include <limits.h>
#include "float_def.h"
#include <stdio.h>
#include <math.h>
#include "common.h"
#include <string.h>
#include <stdint.h>
#include "lut.h"

bool arith_op_divs64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    dst->sdword = (S64)opt1->sdword / opt2->sdword;
    return true;
}

bool arith_op_comp32(Reg64 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->word[0] = opt1->word;
    dst->word[1] = opt2->word;
    return true;
}
bool arith_op_abs64(Reg64 *dst, Reg64 *opt1)
{
    if (opt1->sdword < 0)
    {
        if (INT64_MIN == opt1->sdword)
            dst->sdword = INT64_MAX;
        else
            dst->sdword = -opt1->sdword;
    }
    else
        dst->sdword = opt1->sdword;
    return true;
}

bool arith_op_signed(Reg32 *dst, Reg32 *opt1)
{
    if (0 == opt1->sword)
        dst->sword = 0;
    if (0 < opt1->sword)
        dst->sword = 1;
    if (0 > opt1->sword)
        dst->sword = -1;
    return true;
}

bool arith_op_xor(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->sword = opt1->sword ^ opt2->sword;
    return true;
}

bool arith_op_and64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    dst->sdword = opt1->sdword & opt2->sdword;
    return true;
}

bool arith_op_or64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    dst->sdword = opt1->sdword | opt2->sdword;
    return true;
}

bool arith_op_xor64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    dst->sdword = opt1->sdword ^ opt2->sdword;
    return true;
}

bool arith_op_min64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    dst->sdword = (opt1->sdword < opt2->sdword) ? opt1->sdword : opt2->sdword;
    return true;
}

bool arith_op_max64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    dst->sdword = (opt1->sdword < opt2->sdword) ? opt2->sdword : opt1->sdword;
    return true;
}

bool arith_op_bit_clr(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->sword = opt1->sword & ~(1 << opt2->sword);
    return true;
}

bool arith_op_loop_sr32(Reg128 *dst, Reg128 *opt1, Reg32 *opt2)
{
    dst->sword[0] = opt1->sword[1];
    dst->sword[1] = opt1->sword[2];
    dst->sword[2] = opt1->sword[3];
    dst->sword[3] = opt2->sword;
    return true;
}
bool arith_op_loop_sr16(Reg128 *dst, Reg128 *opt1, Reg32 *opt2)
{
    for (size_t i = 0; i < 7; i++)
    {
        dst->shword[i] = opt1->shword[i + 1];
    }
    dst->shword[7] = opt2->shword[0];
    return true;
}
bool arith_op_loop_sr8(Reg128 *dst, Reg128 *opt1, Reg32 *opt2)
{
    for (size_t i = 0; i < 15; i++)
    {
        dst->byte[i] = opt1->byte[i + 1];
    }
    dst->byte[15] = opt2->byte[0];
    return true;
}

bool arith_op_loop_sl32(Reg128 *dst, Reg128 *opt1, Reg32 *opt2)
{
    dst->sword[1] = opt1->sword[0];
    dst->sword[2] = opt1->sword[1];
    dst->sword[3] = opt1->sword[2];
    dst->sword[0] = opt2->sword;
    return true;
}
bool arith_op_loop_sl16(Reg128 *dst, Reg128 *opt1, Reg32 *opt2)
{
    for (size_t i = 0; i < 7; i++)
    {
        dst->shword[i + 1] = opt1->shword[i];
    }
    dst->shword[0] = opt2->shword[1];
    return true;
}
bool arith_op_loop_sl8(Reg128 *dst, Reg128 *opt1, Reg32 *opt2)
{
    for (size_t i = 0; i < 15; i++)
    {
        dst->byte[i + 1] = opt1->byte[i];
    }
    dst->byte[0] = opt2->byte[0];
    return true;
}

bool arith_op_rd8(Reg32 *dst, Reg128 *opt1, Reg32 *opt2)
{
    dst->byte[0] = opt1->byte[opt2->word];
    for (size_t i = 1; i < 8; i++)
    {
        dst->byte[i] = (U8)0x00;
    }

    return true;
}
bool arith_op_rd16l(Reg32 *dst, Reg128 *opt1, Reg32 *opt2)
{
    dst->shword[0] = opt1->shword[opt2->word];
    if (0x8000 == (dst->shword[0] & 0x8000))
        dst->shword[1] = (U16)0xFFFF;
    else
        dst->shword[1] = (U16)0x0000;
    return true;
}
bool arith_op_rd16h(Reg32 *dst, Reg128 *opt1, Reg32 *opt2)
{
    dst->shword[1] = opt1->shword[opt2->word];
    dst->shword[0] = (U16)0x0000;
    return true;
}

bool arith_op_rd32(Reg32 *dst, Reg128 *opt1, Reg32 *opt2)
{
    dst->sword = opt1->sword[opt2->word];
    return true;
}

bool arith_op_rd64(Reg64 *dst, Reg128 *opt1, Reg32 *opt2)
{
    dst->sdword = opt1->sdword[opt2->word];
    return true;
}

bool arith_op_sl64(Reg64 *dst, Reg64 *opt1, Reg32 *opt2)
{
    S8 shift = opt2->sword;
    if (opt2->sword < 0)
        dst->sdword = opt1->sdword >> (-shift); // (opt1->sdword >> shift) | 0x01
    else
        dst->sdword = opt1->sdword << shift;

    return true;
}

bool arith_op_srs64(Reg64 *dst, Reg64 *opt1, Reg32 *opt2)
{
    S8 shift = opt2->sword;
    if (opt2->sword < 0)
        dst->sdword = opt1->sdword << (-shift);
    else
        dst->sdword = opt1->sdword >> shift;

    return true;
}

bool arith_op_sl32(Reg64 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S64 tmp = opt1->sword;
    dst->sdword = tmp << opt2->sword;

    return true;
}

bool arith_op_fmul(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (is_nan(opt1->word) || is_nan(opt2->word) ||
        (is_inf(opt1->word) && is_zero(opt2->word)) ||
        (is_inf(opt2->word) && is_zero(opt1->word)))
        dst->word = f_qnan;
    else
        dst->f = opt1->f * opt2->f;
    return true;
}
bool arith_op_fadd(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (is_nan(opt1->word) || is_nan(opt2->word) ||
        (f_infinity_n == opt1->word && f_infinity == opt2->word) ||
        (f_infinity == opt1->word && f_infinity_n == opt2->word))
    {
        dst->word = f_qnan;
    }
    else
    {
        dst->f = opt1->f + opt2->f;
    }
    return true;
}
bool arith_op_fsub(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (is_nan(opt1->word) || is_nan(opt2->word) ||
        (f_infinity_n == opt1->word && f_infinity_n == opt2->word) ||
        (f_infinity == opt1->word && f_infinity == opt2->word))
    {
        dst->word = f_qnan;
    }
    else
    {
        dst->f = opt1->f - opt2->f;
    }
    return true;
}
bool arith_op_fmuladd(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    Reg32 reg_a = {0};
    Reg32 reg_b = {0};
    Reg32 reg_c = {0};
    Reg32 reg32_c_ab = {0};

    reg_a.sword = opt1->sword;
    reg_b.sword = opt2->sword;
    reg_c.sword = dst->sword;

    FloatBs fbs_a, fbs_b, fbs_c, fbs_ab, fbs_tmp1, fbs_c_ab;
    if (!handle_special_data_fmuladd(reg_a.sword, reg_b.sword, reg_c.sword, reg32_c_ab.sword))
    {
        // 提取符号
        fbs_a.s = reg_a.sword >> 31;
        fbs_b.s = reg_b.sword >> 31;
        fbs_c.s = reg_c.sword >> 31;

        // 提取指数
        fbs_a.e = ((reg_a.sword >> 23) & 0xFF);
        fbs_b.e = ((reg_b.sword >> 23) & 0xFF);
        fbs_c.e = ((reg_c.sword >> 23) & 0xFF);

        // 提取尾数 规格化的加上整数1, 非规格化左移1位(规格化和非规格化指数统一参照到127)
        fbs_a.m = (0 != fbs_a.e) ? ((reg_a.sword & 0x7FFFFF) + 0x800000) : ((reg_a.sword & 0x7FFFFF) << 1);
        fbs_b.m = (0 != fbs_b.e) ? ((reg_b.sword & 0x7FFFFF) + 0x800000) : ((reg_b.sword & 0x7FFFFF) << 1);
        fbs_c.m = (0 != fbs_c.e) ? ((reg_c.sword & 0x7FFFFF) + 0x800000) : ((reg_c.sword & 0x7FFFFF) << 1);

        // 浮点乘法 符号计算
        fbs_ab.s = fbs_a.s ^ fbs_b.s;

        char sign_ab = fbs_ab.s ? (-1) : (1);
        char sign_c = fbs_c.s ? (-1) : (1);

        // 指数计算
        fbs_ab.e = fbs_a.e + fbs_b.e;

        // 尾数计算
        fbs_ab.m = fbs_a.m * fbs_b.m;

        if (!is_zero(reg_c.sword))
        {
            fbs_c.e += 127;
            fbs_c.m = floor(fbs_c.m * pow(2, 23));
        }

        int shift = fbs_c.e < fbs_ab.e ? (fbs_ab.e - fbs_c.e) : (fbs_c.e - fbs_ab.e);
        fbs_c_ab.e = fbs_c.e < fbs_ab.e ? fbs_ab.e : fbs_c.e;
        fbs_tmp1.m = fbs_c.e < fbs_ab.e ? ((47 < shift) ? (0x0) : floor((sign_c * fbs_c.m) / pow(2, shift))) : ((47 < shift) ? (0x0) : floor((sign_ab * fbs_ab.m) / pow(2, shift)));
        fbs_c_ab.m = fbs_c.e < fbs_ab.e ? (fbs_tmp1.m + sign_ab * fbs_ab.m) : (sign_c * fbs_c.m + fbs_tmp1.m);

        reg32_c_ab.f = fbs_c_ab.m * pow(2, fbs_c_ab.e - 127 * 2 - 46);
        if ((0 < reg32_c_ab.f && reg32_c_ab.f < hex_conv_f(f_min_normal)) || (reg32_c_ab.f < 0 && hex_conv_f(f_min_normal_n) < reg32_c_ab.f)) // 非规格化数直接置零,保留符号
        {
            reg32_c_ab.sword = (0 < reg32_c_ab.f) ? (f_0) : (f_0_n);
        }
    }
    dst->sword = reg32_c_ab.sword;
    return true;
}

bool arith_op_fmulsub(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    Reg32 reg_a = {0};
    Reg32 reg_b = {0};
    Reg32 reg_c = {0};
    Reg32 reg32_c_ab = {0};

    reg_a.sword = opt1->sword;
    reg_b.sword = opt2->sword;
    reg_c.sword = dst->sword;

    FloatBs fbs_a, fbs_b, fbs_c, fbs_ab, fbs_tmp1, fbs_c_ab;
    if (!handle_special_data_fmulsub(reg_a.sword, reg_b.sword, reg_c.sword, reg32_c_ab.sword))
    {
        // 提取符号
        fbs_a.s = reg_a.sword >> 31;
        fbs_b.s = reg_b.sword >> 31;
        fbs_c.s = reg_c.sword >> 31;

        // 提取指数
        fbs_a.e = ((reg_a.sword >> 23) & 0xFF);
        fbs_b.e = ((reg_b.sword >> 23) & 0xFF);
        fbs_c.e = ((reg_c.sword >> 23) & 0xFF);

        // 提取尾数 规格化的加上整数1, 非规格化左移1位(规格化和非规格化指数统一参照到127)
        fbs_a.m = (0 != fbs_a.e) ? ((reg_a.sword & 0x7FFFFF) + 0x800000) : ((reg_a.sword & 0x7FFFFF) << 1);
        fbs_b.m = (0 != fbs_b.e) ? ((reg_b.sword & 0x7FFFFF) + 0x800000) : ((reg_b.sword & 0x7FFFFF) << 1);
        fbs_c.m = (0 != fbs_c.e) ? ((reg_c.sword & 0x7FFFFF) + 0x800000) : ((reg_c.sword & 0x7FFFFF) << 1);

        // 浮点乘法 符号计算
        fbs_ab.s = fbs_a.s ^ fbs_b.s;

        char sign_ab = fbs_ab.s ? (-1) : (1);
        char sign_c = fbs_c.s ? (-1) : (1);

        // 指数计算
        fbs_ab.e = fbs_a.e + fbs_b.e;

        // 尾数计算
        fbs_ab.m = fbs_a.m * fbs_b.m;

        if (!is_zero(reg_c.sword))
        {
            fbs_c.e += 127;
            fbs_c.m = floor(fbs_c.m * pow(2, 23));
        }

        int shift = fbs_c.e < fbs_ab.e ? (fbs_ab.e - fbs_c.e) : (fbs_c.e - fbs_ab.e);
        fbs_c_ab.e = fbs_c.e < fbs_ab.e ? fbs_ab.e : fbs_c.e;
        fbs_tmp1.m = fbs_c.e < fbs_ab.e ? ((47 < shift) ? (0x0) : floor((sign_c * fbs_c.m) / pow(2, shift))) : ((47 < shift) ? (0x0) : floor(((-sign_ab) * fbs_ab.m) / pow(2, shift)));
        fbs_c_ab.m = fbs_c.e < fbs_ab.e ? (fbs_tmp1.m + (-sign_ab) * fbs_ab.m) : (sign_c * fbs_c.m + fbs_tmp1.m);

        reg32_c_ab.f = fbs_c_ab.m * pow(2, fbs_c_ab.e - 127 * 2 - 46);
        if ((0 < reg32_c_ab.f && reg32_c_ab.f < hex_conv_f(f_min_normal)) || (reg32_c_ab.f < 0 && hex_conv_f(f_min_normal_n) < reg32_c_ab.f)) // 非规格化数直接置零,保留符号
        {
            reg32_c_ab.sword = (0 < reg32_c_ab.f) ? (f_0) : (f_0_n);
        }
    }
    dst->sword = reg32_c_ab.sword;

    return true;
}

bool arith_op_f32toi64(Reg64 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S8 s = (0x01 == ((opt1->word >> 31) & 0x01)) ? (-1) : (1);

    double tmp1 = s * fabs(opt1->f) * pow(2, 63 - opt2->word);
    if (INT64_MAX <= tmp1)
        dst->sdword = INT64_MAX;
    else if (tmp1 < INT64_MIN)
        dst->sdword = INT64_MIN;
    else
        dst->sdword = tmp1;

    return true;
}

bool arith_op_i8tof32(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->f = opt1->byte[0] / pow(2, 8 - opt2->word);
    return true;
}

bool arith_op_fmin(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (is_nan(opt1->word) || is_nan(opt2->word))
        dst->word = f_qnan;
    else if ((0x80 == (opt1->byte[3] & 0x80)) && (0x00 == (opt2->byte[3] & 0x80)))
        dst->word = opt1->word;
    else if ((0x00 == (opt1->byte[3] & 0x80)) && (0x80 == (opt2->byte[3] & 0x80)))
        dst->word = opt2->word;
    else
        dst->f = (opt1->f < opt2->f) ? opt1->f : opt2->f; // f_0 和 f_0_n比较不了 所以上面用判断符号方式
    return true;
}

bool arith_op_fmax(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (is_nan(opt1->word) || is_nan(opt2->word))
        dst->word = f_qnan;
    else if ((0x80 == (opt1->byte[3] & 0x80)) && (0x00 == (opt2->byte[3] & 0x80)))
        dst->word = opt2->word;
    else if ((0x00 == (opt1->byte[3] & 0x80)) && (0x80 == (opt2->byte[3] & 0x80)))
        dst->word = opt1->word;
    else
        dst->f = (opt1->f < opt2->f) ? opt2->f : opt1->f; // f_0 和 f_0_n比较不了 所以上面用判断符号方式
    return true;
}
bool arith_op_fabs(Reg32 *dst, Reg32 *opt1)
{
    dst->f = fabsf(opt1->f);
    return true;
}

bool arith_op_flog2(Reg32 *dst, Reg32 *opt1)
{
    if ((opt1->word > 31) & 0x01)
        dst->word = f_qnan;
    else
        dst->f = log2(opt1->f);
    return true;
}

/**
 * 特别说明: 该指令多了一个参数reg_r38,实际指令没这个参数,主要是通过程序控制r38的变化
 * 指令: atk_rls r0, r1, r2
 */
bool arith_op_atk_rls(Reg32 *dst, Reg32 *opt1, Reg32 *opt2, S32 reg_r38)
{
    S16 alpha = reg_r38 >> 16;
    S16 belta = reg_r38 & 0xFFFF;
    S32 c = opt2->sword <= opt1->sword ? alpha : belta;
    // printf("opt1=0x%08x opt2=0x%08x c=%d\n", opt1->sword, opt2->sword, c);
    S64 a = opt1->sword;
    S64 b = opt2->sword;
    // __int128_t d = c * (a - b);
    // double e = opt2->sword * pow(2, 15);
    // double f = round((d + e) / pow(2, 15));
    double e = floor(c * (a - b) / pow(2, 15));
    double f = e + b;
    if (f > INT32_MAX)
        dst->sword = INT32_MAX;
    else if (f < INT32_MIN)
        dst->sword = INT32_MIN;
    else
        dst->sword = (S32)f;
    return true;
}

bool arith_op_muls64_64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    __int128_t a = opt1->sdword;
    __int128_t b = opt2->sdword;
    __int128_t product = a * b;
    dst->sdword = product & 0xFFFFFFFFFFFFFFFF;
    return true;
}
bool arith_op_mulc_32o(Reg64 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 a = opt1->shword[1]; // 实部
    S32 b = opt1->shword[0]; // 虚部
    S32 c = opt2->shword[1]; // 实部
    S32 d = opt2->shword[0]; // 虚部

    S64 A = (a * c - b * d); // m2p30
    S64 B = (a * d + b * c); // m2p30

    if (A < INT32_MIN)
        dst->sword[0] = INT32_MIN;
    else if (A > INT32_MAX)
        dst->sword[0] = INT32_MAX;
    else
        dst->sword[0] = (S32)A;

    if (B < INT32_MIN)
        dst->sword[1] = INT32_MIN;
    else if (B > INT32_MAX)
        dst->sword[1] = INT32_MAX;
    else
        dst->sword[1] = (S32)B;

    return true;
}

bool arith_op_mulc32_16(Reg64 *dst, Reg64 *opt1, Reg32 *opt2)
{
    S64 a = opt1->sword[0];  // 实部
    S64 b = opt1->sword[1];  // 虚部
    S32 c = opt2->shword[1]; // 实部
    S32 d = opt2->shword[0]; // 虚部

    S64 a1 = a * c;
    S64 a2 = b * d;
    S64 a3 = a * d;
    S64 a4 = b * c;

    S64 r = a1 - a2;
    double A = floor(r / pow(2, 15)); // 实部
    if (A < INT32_MIN)
        dst->sword[0] = INT32_MIN;
    else if (INT32_MAX <= A)
        dst->sword[0] = INT32_MAX;
    else
        dst->sword[0] = A;

    S64 i = a3 + a4;
    double B = floor(i / pow(2, 15)); // 虚部
    if (B < INT32_MIN)
        dst->sword[1] = INT32_MIN;
    else if (INT32_MAX <= B)
        dst->sword[1] = INT32_MAX;
    else
        dst->sword[1] = B;
    return true;
}

bool arith_op_mulc32_32(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    S64 a = opt1->sword[0]; // 实部
    S64 b = opt1->sword[1]; // 虚部
    S64 c = opt2->sword[0]; // 实部
    S64 d = opt2->sword[1]; // 虚部

    S64 a1 = a * c;
    S64 a2 = b * d;
    S64 a3 = a * d;
    S64 a4 = b * c;

    S64 r = a1 - a2;
    double A = floor(r / pow(2, 31)); // 实部
    if (A < INT32_MIN)
        dst->sword[0] = INT32_MIN;
    else if (INT32_MAX <= A)
        dst->sword[0] = INT32_MAX;
    else
        dst->sword[0] = A;

    S64 i = a3 + a4;
    double B = floor(i / pow(2, 31)); // 虚部
    if (B < INT32_MIN)
        dst->sword[1] = INT32_MIN;
    else if (INT32_MAX <= B)
        dst->sword[1] = INT32_MAX;
    else
        dst->sword[1] = B;
    return true;
}

bool arith_op_conj32(Reg64 *dst, Reg64 *opt1)
{
    S32 a = opt1->sword[0]; // 实部
    S32 b = opt1->sword[1]; // 虚部

    dst->sword[0] = a;
    if (INT32_MIN == b)
        dst->sword[1] = INT32_MAX; // 溢出
    else
        dst->sword[1] = -b;

    return true;
}

bool arith_op_add_c32(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    S64 a = opt1->sword[0]; // 实部
    S64 b = opt1->sword[1]; // 虚部
    S64 c = opt2->sword[0]; // 实部
    S64 d = opt2->sword[1]; // 虚部

    S64 A = (a + c);
    S64 B = (b + d);

    if (A < INT32_MIN)
        dst->sword[0] = INT32_MIN;
    else if (A > INT32_MAX)
        dst->sword[0] = INT32_MAX;
    else
        dst->sword[0] = (S32)A;

    if (B < INT32_MIN)
        dst->sword[1] = INT32_MIN;
    else if (B > INT32_MAX)
        dst->sword[1] = INT32_MAX;
    else
        dst->sword[1] = (S32)B;

    return true;
}

bool arith_op_sub_c32(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    S64 a = opt1->sword[0]; // 实部
    S64 b = opt1->sword[1]; // 虚部
    S64 c = opt2->sword[0]; // 实部
    S64 d = opt2->sword[1]; // 虚部

    S64 A = a - c;
    S64 B = b - d;

    if (A < INT32_MIN)
        dst->sword[0] = INT32_MIN;
    else if (A > INT32_MAX)
        dst->sword[0] = INT32_MAX;
    else
        dst->sword[0] = (S32)A;

    if (B < INT32_MIN)
        dst->sword[1] = INT32_MIN;
    else if (B > INT32_MAX)
        dst->sword[1] = INT32_MAX;
    else
        dst->sword[1] = (S32)B;

    return true;
}

/**
 * 功能:复数共轭乘法,opt2表示的复数的共轭与opt1表示的复数相乘
 * 说明:计算过程中的乘法异常处理遵循浮点乘法异常处理,加减法只判断
 * 遵循浮点加减法无效值处理规则。故对于非无效值情况,都用double数据
 * 存储,然后进行运算,最后强转float类型
 */
bool arith_op_fmulc_conj(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    Reg32 reg_a = {0};
    Reg32 reg_b = {0};
    Reg32 reg_c = {0};
    Reg32 reg_d = {0};
    Reg32 reg32_ac_bd = {0};
    Reg32 reg32_bc_ad = {0};

    FloatBs fbs_a, fbs_b, fbs_c, fbs_d, fbs_ac, fbs_bd, fbs_bc, fbs_ad, fbs_tmp1, fbs_tmp2, fbs_ac_bd, fbs_bc_ad;

    reg_a.f = opt1->f[0];
    reg_b.f = opt1->f[1];
    reg_c.f = opt2->f[0];
    reg_d.f = opt2->f[1];

    if (!is_nan(reg_d.sword))
        reg_d.f = -reg_d.f; // d取共轭

    if (!handle_special_data_fmulc(reg_a.sword, reg_b.sword, reg_c.sword, reg_d.sword, reg32_ac_bd.sword, reg32_bc_ad.sword))
    {
        // 提取符号
        fbs_a.s = reg_a.sword >> 31;
        fbs_b.s = reg_b.sword >> 31;
        fbs_c.s = reg_c.sword >> 31;
        fbs_d.s = reg_d.sword >> 31;

        // 提取指数
        fbs_a.e = ((reg_a.sword >> 23) & 0xFF);
        fbs_b.e = ((reg_b.sword >> 23) & 0xFF);
        fbs_c.e = ((reg_c.sword >> 23) & 0xFF);
        fbs_d.e = ((reg_d.sword >> 23) & 0xFF);

        // 提取尾数 规格化的加上整数1, 非规格化左移1位(规格化和非规格化指数统一参照到127)
        fbs_a.m = (0 != fbs_a.e) ? ((reg_a.sword & 0x7FFFFF) + 0x800000) : ((reg_a.sword & 0x7FFFFF) << 1);
        fbs_b.m = (0 != fbs_b.e) ? ((reg_b.sword & 0x7FFFFF) + 0x800000) : ((reg_b.sword & 0x7FFFFF) << 1);
        fbs_c.m = (0 != fbs_c.e) ? ((reg_c.sword & 0x7FFFFF) + 0x800000) : ((reg_c.sword & 0x7FFFFF) << 1);
        fbs_d.m = (0 != fbs_d.e) ? ((reg_d.sword & 0x7FFFFF) + 0x800000) : ((reg_d.sword & 0x7FFFFF) << 1);

        // 浮点乘法 符号计算
        fbs_ac.s = fbs_a.s ^ fbs_c.s;
        fbs_bd.s = fbs_b.s ^ fbs_d.s;
        fbs_bc.s = fbs_b.s ^ fbs_c.s;
        fbs_ad.s = fbs_a.s ^ fbs_d.s;

        char sign_ac = fbs_ac.s ? (-1) : (1);
        char sign_bd = fbs_bd.s ? (-1) : (1);
        char sign_bc = fbs_bc.s ? (-1) : (1);
        char sign_ad = fbs_ad.s ? (-1) : (1);

        // 指数计算
        fbs_ac.e = fbs_a.e + fbs_c.e;
        fbs_bd.e = fbs_b.e + fbs_d.e;
        fbs_bc.e = fbs_b.e + fbs_c.e;
        fbs_ad.e = fbs_a.e + fbs_d.e;

        // 尾数计算
        fbs_ac.m = fbs_a.m * fbs_c.m;
        fbs_bd.m = fbs_b.m * fbs_d.m;
        fbs_bc.m = fbs_b.m * fbs_c.m;
        fbs_ad.m = fbs_a.m * fbs_d.m;

        int shift = 0;

        if (0x0 == fbs_ac.m && -1 == sign_ac && 1 == sign_bd && 0x0 == fbs_bd.m) // f_0_n - f_n
            reg32_ac_bd.sword = f_0_n;
        else
        {
            shift = fbs_ac.e < fbs_bd.e ? (fbs_bd.e - fbs_ac.e) : (fbs_ac.e - fbs_bd.e);
            fbs_ac_bd.e = fbs_ac.e < fbs_bd.e ? fbs_bd.e : fbs_ac.e;
            fbs_tmp1.m = fbs_ac.e < fbs_bd.e ? ((47 < shift) ? (0x0) : floor((sign_ac * fbs_ac.m) / pow(2, shift))) : ((47 < shift) ? (0x0) : floor(((-sign_bd) * fbs_bd.m) / pow(2, shift)));
            fbs_ac_bd.m = fbs_ac.e < fbs_bd.e ? (fbs_tmp1.m + (-sign_bd) * fbs_bd.m) : (sign_ac * fbs_ac.m + fbs_tmp1.m);

            reg32_ac_bd.f = fbs_ac_bd.m * pow(2, fbs_ac_bd.e - 127 * 2 - 46);
            if ((0 < reg32_ac_bd.f && reg32_ac_bd.f < hex_conv_f(f_min_normal)) || (reg32_ac_bd.f < 0 && hex_conv_f(f_min_normal_n) < reg32_ac_bd.f)) // 非规格化数直接置零,保留符号
            {
                reg32_ac_bd.sword = (0 < reg32_ac_bd.f) ? (f_0) : (f_0_n);
            }
        }
        if (0x0 == fbs_bc.m && -1 == sign_bc && -1 == sign_ad && 0x0 == fbs_ad.m) // f_0_n - f_n
            reg32_bc_ad.sword = f_0_n;
        else
        {
            shift = fbs_bc.e < fbs_ad.e ? (fbs_ad.e - fbs_bc.e) : (fbs_bc.e - fbs_ad.e);
            fbs_bc_ad.e = fbs_bc.e < fbs_ad.e ? fbs_ad.e : fbs_bc.e;
            fbs_tmp2.m = fbs_bc.e < fbs_ad.e ? ((47 < shift) ? (0x0) : floor((sign_bc * fbs_bc.m) / pow(2, shift))) : ((47 < shift) ? (0x0) : floor((sign_ad * fbs_ad.m) / pow(2, shift)));
            fbs_bc_ad.m = fbs_bc.e < fbs_ad.e ? (fbs_tmp2.m + sign_ad * fbs_ad.m) : (sign_bc * fbs_bc.m + fbs_tmp2.m);

            reg32_bc_ad.f = fbs_bc_ad.m * pow(2, fbs_bc_ad.e - 127 * 2 - 46);
            if ((0 < reg32_bc_ad.f && reg32_bc_ad.f < hex_conv_f(f_min_normal)) || (reg32_bc_ad.f < 0 && hex_conv_f(f_min_normal_n) < reg32_bc_ad.f))
            {
                reg32_bc_ad.sword = (0 < reg32_bc_ad.f) ? (f_0) : (f_0_n);
            }
        }
    }

    dst->sword[0] = reg32_ac_bd.sword;
    dst->sword[1] = reg32_bc_ad.sword;

    return true;
}

bool arith_op_rpc16(Reg32 *dst, Reg64 *opt1, Reg32 *opt2)
{
    if (0 == opt2->word)
    {
        if (opt1->sword[0] > INT16_MAX)
            dst->shword[1] = INT16_MAX;
        else if (opt1->sword[0] < INT16_MIN)
            dst->shword[1] = INT16_MIN;
        else
            dst->shword[1] = opt1->sword[0] & 0xFF; // 实部

        if (opt1->sword[1] > INT16_MAX)
            dst->shword[0] = INT16_MAX;
        else if (opt1->sword[1] < INT16_MIN)
            dst->shword[0] = INT16_MIN;
        else
            dst->shword[0] = opt1->sword[1] & 0xFF; // 虚部
    }
    else
    {
        S32 tmp = 0;
        tmp = (S32)round(opt1->sword[0] / pow(2, 16));
        if (tmp > INT16_MAX)
            dst->shword[1] = INT16_MAX;
        else if (tmp < INT16_MIN)
            dst->shword[1] = INT16_MIN;
        else
            dst->shword[1] = (S16)tmp;

        tmp = (S32)round(opt1->sword[1] / pow(2, 16));
        if (tmp > INT16_MAX)
            dst->shword[0] = INT16_MAX;
        else if (tmp < INT16_MIN)
            dst->shword[0] = INT16_MIN;
        else
            dst->shword[0] = (S16)tmp;
    }
    return true;
}

bool arith_op_cvt32_16(Reg32 *dst, Reg32 *opt1)
{
    double tmp = round(opt1->sword / pow(2, 16));
    if (tmp > INT16_MAX)
        dst->shword[1] = INT16_MAX;
    else if (tmp < INT16_MIN)
        dst->shword[1] = INT16_MIN;
    else
        dst->shword[1] = tmp;
    dst->shword[0] = 0x0000;
    return true;
}

bool arith_op_frelu(Reg32 *dst, Reg32 *opt1)
{
    if (0x01 == ((opt1->sword >> 31) & 0x01))
        dst->f = f_0;
    else
        dst->f = opt1->f;
    return true;
}
bool arith_op_fleaky(Reg32 *dst, Reg32 *opt1)
{
    if (0x01 == ((opt1->sword >> 31) & 0x01))
    {
        if (f_snan == opt1->word) // u31与c不一致的地方
            dst->word = f_qnan;
        else
            dst->f = opt1->f / 16;
    }
    else
        dst->f = opt1->f;
    return true;
}
bool arith_op_fsl(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (is_nan(opt1->word))
    {
        dst->word = f_qnan;
        return true;
    }
    if (is_inf(opt1->word))
    {
        dst->word = opt1->word;
        return true;
    }
    if (is_zero(opt1->word))
    {
        dst->word = opt1->word;
        return true;
    }

    S32 shift = opt2->sword;
    if (shift < 0)
        dst->f = opt1->f / pow(2, -shift);
    else
        dst->f = opt1->f * pow(2, shift);

    return true;
}
bool arith_op_fdiv(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    int32_t s1, s2;
    s1 = GET_BIT(opt1->word, 31) ? (-1) : (1);
    s2 = GET_BIT(opt2->word, 31) ? (-1) : (1);
    if (is_nan(opt1->word) || is_nan(opt2->word))
        dst->word = f_qnan; //
    else if (is_zero(opt2->word))
        dst->word = f_qnan;
    else if (is_inf(opt1->word))
    {
        if (is_inf(opt2->word))
            dst->word = f_qnan;
        else
            dst->word = (s1 * s2 < 0) ? (f_infinity_n) : (f_infinity);
    }
    else if (is_inf(opt2->word))
    {
        dst->word = (s1 * s2 < 0) ? (f_0_n) : (f_0);
    }
    else
    {
        int32_t s = 1, n = 0, n1 = 0, n2 = 0, n3 = 0;
        double m = 0.0, p = 0.0, k = 0.0, q = 0.0;
        int32_t m1, m2;
        // s*m*2^n
        m1 = frexpf_ext(opt1->f, &n1);
        m2 = frexpf_ext(opt2->f, &n2);

        s = s1 * s2;
        n = n1 - n2;
        m = fabs(m1) / fabs(m2);
        p = m * pow(2, 39); // 放大2^40及后面的取整后除以2^40,目的是保留40位精度与U31精度保持一致 (为了与u31一致,原因未知,不知道是否是u31做了特殊处理,此处只保留39位)
        q = floor(p);
        k = q / pow(2, 39);
        dst->f = (float)s * k * pow(2, n);

        // static int cnt = 0;
        // printf("%d\tin1:0x%08x %f, n1=%d, m1=%d; \n\tin2:0x%08x %f, n2=%d, m2=%d;\n\tm=%llf, p=%llf, q=%llf, s=%d, n=%d k=%llf;\n\tdst->f:0x%08x %f\n",
        //        cnt++, opt1->word, opt1->f, n1, m1, opt2->word, opt2->f, n2, m2, m, p, q, s, n, k, dst->word, dst->f);
        // printf("--------------------------------------------------------\n");
    }
    return true;
}

bool arith_op_fsqrt(Reg32 *dst, Reg32 *opt1)
{
    if (CHECK_BIT(opt1->word, 31))
    {
        dst->word = f_0;
        return true;
    }
    if (is_inf(opt1->word))
    {
        dst->word = opt1->word;
        return true;
    }
    int s, n;
    float m, exponent, mantissa;
    m = frexpf(opt1->f, &n);

    if (n % 2)
    {
        m /= 2;
        n += 1;
    }
    // 先计算指数开方
    exponent = pow(2, n / 2);
    // 计算尾数开方 先转成整数
    m *= pow(2, 31);
    Reg32 tmp, value;
    value.word = m;

    arith_op_sqrtf(&tmp, &value);
    mantissa = tmp.word / pow(2, 31);
    dst->f = exponent * mantissa;

    return true;
}

bool arith_op_comp16(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->shword[0] = opt1->shword[1];
    dst->shword[1] = opt2->shword[1];
    return true;
}

bool arith_op_slc(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 shift = opt2->sword;
    if (shift < -15 || shift > 15)
    {
        printf("opt2 is invalid. %d\n", shift);
        return false;
    }

    S32 real = opt1->shword[1]; // 实部
    S32 imag = opt1->shword[0]; // 虚部

    if (shift < 0)
    {
        real = real >> -shift;
        imag = imag >> -shift;
    }
    else
    {
        real = real << shift;
        imag = imag << shift;
    }
    if (real < INT16_MIN)
        real = INT16_MIN;
    if (real > INT16_MAX)
        real = INT16_MAX;

    if (imag < INT16_MIN)
        imag = INT16_MIN;
    if (imag > INT16_MAX)
        imag = INT16_MAX;

    dst->shword[1] = real;
    dst->shword[0] = imag;
    return true;
}

bool arith_op_src(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 shift = opt2->sword;
    if (shift < -15 || shift > 15)
    {
        printf("opt2 is invalid. %d\n", shift);
        return false;
    }

    S32 real = opt1->shword[1]; // 实部
    S32 imag = opt1->shword[0]; // 虚部

    if (shift < 0)
    {
        real = real << -shift;
        imag = imag << -shift;
    }
    else
    {
        real = real >> shift;
        imag = imag >> shift;
    }
    if (real < INT16_MIN)
        real = INT16_MIN;
    if (real > INT16_MAX)
        real = INT16_MAX;

    if (imag < INT16_MIN)
        imag = INT16_MIN;
    if (imag > INT16_MAX)
        imag = INT16_MAX;

    dst->shword[1] = real;
    dst->shword[0] = imag;
    return true;
}

bool arith_op_conj(Reg32 *dst, Reg32 *opt1)
{
    S32 real = opt1->shword[1];
    S32 imag = opt1->shword[0];

    dst->shword[1] = real;
    if (INT16_MIN == imag)
        dst->shword[0] = INT16_MAX; // 溢出
    else
        dst->shword[0] = -imag;
    return true;
}

bool arith_op_add_c(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 a = opt1->shword[1]; // 实部
    S32 b = opt1->shword[0]; // 虚部
    S32 c = opt2->shword[1]; // 实部
    S32 d = opt2->shword[0]; // 虚部

    S32 A = (a + c);
    S32 B = (b + d);

    if (A < INT16_MIN)
        dst->shword[1] = INT16_MIN;
    else if (A > INT16_MAX)
        dst->shword[1] = INT16_MAX;
    else
        dst->shword[1] = (S16)A;

    if (B < INT16_MIN)
        dst->shword[0] = INT16_MIN;
    else if (B > INT16_MAX)
        dst->shword[0] = INT16_MAX;
    else
        dst->shword[0] = (S16)B;

    return true;
}

bool arith_op_sub_c(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 a = opt1->shword[1]; // 实部
    S32 b = opt1->shword[0]; // 虚部
    S32 c = opt2->shword[1]; // 实部
    S32 d = opt2->shword[0]; // 虚部

    S32 A = (a - c);
    S32 B = (b - d);

    if (A < INT16_MIN)
        dst->shword[1] = INT16_MIN;
    else if (A > INT16_MAX)
        dst->shword[1] = INT16_MAX;
    else
        dst->shword[1] = (S16)A;

    if (B < INT16_MIN)
        dst->shword[0] = INT16_MIN;
    else if (B > INT16_MAX)
        dst->shword[0] = INT16_MAX;
    else
        dst->shword[0] = (S16)B;

    return true;
}

bool arith_op_fadd_c(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    Reg32 a, b, c, d;

    a.f = opt1->f[0]; // 实部
    b.f = opt1->f[1]; // 虚部
    c.f = opt2->f[0]; // 实部
    d.f = opt2->f[1]; // 虚部

    Reg32 A, B;

    arith_op_fadd(&A, &a, &c);
    arith_op_fadd(&B, &b, &d);

    dst->sword[0] = A.sword;
    dst->sword[1] = B.sword;

    return true;
}

bool arith_op_fsub_c(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    Reg32 a, b, c, d;

    a.f = opt1->f[0]; // 实部
    b.f = opt1->f[1]; // 虚部
    c.f = opt2->f[0]; // 实部
    d.f = opt2->f[1]; // 虚部

    Reg32 A, B;

    arith_op_fsub(&A, &a, &c);
    arith_op_fsub(&B, &b, &d);

    dst->sword[0] = A.sword;
    dst->sword[1] = B.sword;

    return true;
}

bool arith_op_fconj(Reg64 *dst, Reg64 *opt1)
{
    dst->f[0] = opt1->f[0];
    dst->f[1] = -opt1->f[1];
    return true;
}

bool arith_op_add(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S64 a = opt1->sword;
    S64 c = opt2->sword;

    S64 A = (a + c);

    if (A < INT32_MIN)
        dst->sword = INT32_MIN;
    else if (A > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = (S32)A;

    return true;
}

bool arith_op_sub(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S64 a = opt1->sword;
    S64 c = opt2->sword;

    S64 A = (a - c);

    if (A < INT32_MIN)
        dst->sword = INT32_MIN;
    else if (A > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = (S32)A;

    return true;
}

bool arith_op_add64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    S64 a = opt1->sdword;
    S64 c = opt2->sdword;

    S64 A = (a + c);

    if (a > 0 && c > 0 && A < 0)
        dst->sdword = INT64_MAX;
    else if (a < 0 && c < 0 && A > 0)
        dst->sdword = INT64_MIN;
    else
        dst->sdword = A;

    return true;
}

bool arith_op_sub64(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    S64 a = opt1->sdword;
    S64 c = opt2->sdword;

    S64 A = (a - c);

    if (a > 0 && c < 0 && A < 0)
        dst->sdword = INT64_MAX;
    else if (a < 0 && c > 0 && A > 0)
        dst->sdword = INT64_MIN;
    else
        dst->sdword = A;

    return true;
}

bool arith_op_fneg(Reg32 *dst, Reg32 *opt1)
{
    dst->f = -opt1->f;
    return true;
}

bool arith_op_abs(Reg32 *dst, Reg32 *opt1)
{
    if (INT32_MIN == opt1->sword)
        dst->sword = INT32_MAX;
    else
        dst->sword = fabs(opt1->sword);

    return true;
}

bool arith_op_and(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->sword = opt1->sword & opt2->sword;
    return true;
}

bool arith_op_or(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->sword = opt1->sword | opt2->sword;
    return true;
}
bool arith_op_cvt32_64(Reg64 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (0 == opt2->sword)
    {
        dst->sword[0] = opt1->sword;
        dst->sword[1] = (0 <= opt1->sword) ? (0x00000000) : (0xFFFFFFFF);
    }
    else if (1 == opt2->sword)
    {
        dst->sword[1] = opt1->sword;
        dst->sword[0] = 0x00000000;
    }
    else if (2 == opt2->sword)
    {
        dst->sword[0] = opt1->sword;
        dst->sword[1] = 0x00000000;
    }

    return true;
}

bool arith_op_min(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->sword = (opt1->sword < opt2->sword) ? opt1->sword : opt2->sword;
    return true;
}

bool arith_op_max(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->sword = (opt1->sword < opt2->sword) ? opt2->sword : opt1->sword;
    return true;
}

bool arith_op_bit_set(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->sword = opt1->sword;
    SET_BIT(dst->sword, opt2->sword);
    return true;
}

bool arith_op_sl(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S8 shift = opt2->sword;
    if (opt2->sword < 0)
        dst->sword = opt1->sword >> (-shift); // (opt1->sdword >> shift) | 0x01
    else
        dst->sword = opt1->sword << shift;

    return true;
}
// 算术移位
bool arith_op_srs(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 shift = opt2->sword;
    S64 tmp;
    S64 op = opt1->sword;
    if (opt2->sword < 0)
        tmp = op << (-shift);
    else
        tmp = op >> shift;

    if (tmp < INT32_MIN)
        dst->sword = INT32_MIN;
    else if (tmp > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = (S32)tmp;
    return true;
}
// 算术移位 需要保留符号位
bool arith_op_slp(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 shift = opt2->sword;
    S64 tmp;
    S64 op = opt1->sword; // 算术移位,需要保留符号位. 1.通过扩大数据类型将符号位补充到高位,不影响移位;2.通过除法向下取整
    if (opt2->sword < 0)
        tmp = op >> (-shift);
    else
        tmp = op << shift;

    if (tmp < INT32_MIN)
        dst->sword = INT32_MIN;
    else if (tmp > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = (S32)tmp;
    return true;
}
// 逻辑移位 不需要保留符号位,直接移就行
bool arith_op_sru(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S8 shift = opt2->sword;
    S64 tmp;

    if (opt2->sword < 0)
        dst->word = opt1->word << (-shift);
    else
        dst->word = opt1->word >> shift;

    return true;
}

bool arith_op_divs32f(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (0 == opt2->sword)
        dst->sword = (GET_BIT(opt1->sword, 31)) ? INT32_MIN : INT32_MAX;
    else
    {
        double a = opt1->sword / pow(2, 16);
        double b = opt2->sword / pow(2, 16);
        double tmp = a / b;
        dst->sword = (S32)round(tmp * pow(2, 16));
    }

    return true;
}

bool arith_op_divs32(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (0x00000000 == opt2->sword)
    {
        dst->sword = (GET_BIT(opt1->sword, 31)) ? INT32_MIN : INT32_MAX;
        return true;
    }

    double tmp = opt1->sword / opt2->sword;

    if (tmp > INT32_MAX)
        dst->sword = INT32_MAX;
    else if (tmp < INT32_MIN)
        dst->sword = INT32_MIN; // 此处不应该进入
    else
        dst->sword = (S32)floor(tmp);

    return true;
}
bool arith_op_divs64_32(Reg64 *dst, Reg64 *opt1, Reg32 *opt2)
{
    if (0x00000000 == opt2->sword)
    {
        dst->sdword = (GET_BIT(opt1->sdword, 63)) ? INT64_MIN : INT64_MAX;
        return true;
    }

    double tmp = opt1->sdword / opt2->sword;

    // if (tmp > INT64_MAX) // 不存在溢出
    //     dst->sdword = INT64_MAX;
    // else if (tmp < INT64_MIN)
    //     dst->sdword = INT64_MIN; // 此处不应该进入
    // else
    dst->sdword = floor(tmp);

    return true;
}

bool arith_op_sqrt(Reg32 *dst, Reg32 *opt1)
{
    S32 nHat = 0;
    S32 b = 32768;
    S32 bshft = 15;
    S32 valid;

    for (int i = 0; i < 16; ++i)
    {
        S32 tmps = ((nHat * 2) + b);
        S32 tmp = tmps << bshft;

        valid = (opt1->sword >= tmp) ? 1 : 0;

        if (valid)
        {
            nHat += b;
            opt1->sword -= tmp;
        }

        b >>= 1;

        bshft--;
    }
    dst->sword = nHat;
    return true;
}

bool arith_op_sqrtf(Reg32 *dst, Reg32 *opt1)
{
    S32 nHat = 0;
    S32 b = 32768;
    S32 bshft = 15;
    S32 valid;

    for (int i = 0; i < 16; ++i)
    {
        S32 tmps = ((nHat * 2) + b);
        S32 tmp = tmps << bshft;

        valid = (opt1->sword >= tmp) ? 1 : 0;

        if (valid)
        {
            nHat += b;
            opt1->sword -= tmp;
        }

        b >>= 1;

        bshft--;
    }
    dst->sword = nHat * 46341;

    return true;
}

bool arith_op_muls16(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 a = opt1->shword[0];
    S32 b = opt2->shword[0];
    dst->sword = a * b;

    return true;
}

bool arith_op_muls16f(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 a = opt1->shword[1];
    S32 b = opt2->shword[1];
    S64 product = a * b * pow(2, 1); // 注意溢出 扩大数据类型
    if (product < INT32_MIN)
        dst->sword = INT32_MIN;
    else if (product > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = product;

    return true;
}

bool arith_op_muls32(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S64 a = opt1->sword;
    S64 b = opt2->sword;
    S32 product = (a * b) & 0xFFFFFFFF; // 直接取低位存32位地址 不存在溢出
                                        // if (product < INT32_MIN)
                                        //     dst->sword = INT32_MIN;
                                        // else if (product > INT32_MAX)
                                        //     dst->sword = INT32_MAX;
                                        // else
    dst->sword = product;

    return true;
}

bool arith_op_muls32f(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S64 a = opt1->sword;
    S64 b = opt2->sword;
    double product = (a * b) / pow(2, 31);
    if (product < INT32_MIN)
        dst->sword = INT32_MIN;
    else if (product > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = floor(product); // dst->sword = round(product);   20241029 modify

    return true;
}

bool arith_op_muls32_64(Reg64 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S64 a = opt1->sword;
    S64 b = opt2->sword;
    dst->sdword = a * b;

    return true;
}

bool arith_op_muls64_32(Reg64 *dst, Reg64 *opt1, Reg32 *opt2)
{
    S64 a = opt1->sdword;
    S64 b = opt2->sword;
    __int128_t product = a * b;
    dst->sdword = product & 0xFFFFFFFFFFFFFFFF;

    return true;
}

bool arith_op_muls64_32f(Reg64 *dst, Reg64 *opt1, Reg32 *opt2)
{
    __int128_t a, b, product;
    a = opt1->sdword;
    b = opt2->sword;
    product = a * b * 2; // 乘法后移位操作,必须在乘完后扩1位,因为两个乘数的符号位各占1位,导致乘后的位数比两个乘数的位数和少1位,所以需再扩1位
    dst->sdword = product >> 32;

    return true;
}

bool arith_op_mulc(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    S32 a = opt1->shword[1];
    S32 b = opt1->shword[0];
    S32 c = opt2->shword[1];
    S32 d = opt2->shword[0];

    S32 ac = a * c;
    S32 bd = b * d;
    S32 bc = b * c;
    S32 ad = a * d;

    S64 real = ac - bd;
    S64 imag = bc + ad;

    real = round(real / pow(2, 15));
    if (real > INT16_MAX)
        dst->shword[1] = INT16_MAX;
    else if (real < INT16_MIN)
        dst->shword[1] = INT16_MIN;
    else
        dst->shword[1] = (S16)real;

    imag = round(imag / pow(2, 15));
    if (imag > INT16_MAX)
        dst->shword[0] = INT16_MAX;
    else if (imag < INT16_MIN)
        dst->shword[0] = INT16_MIN;
    else
        dst->shword[0] = (S16)imag;

    return true;
}

bool arith_op_fmulc(Reg64 *dst, Reg64 *opt1, Reg64 *opt2)
{
    Reg32 reg_a = {0};
    Reg32 reg_b = {0};
    Reg32 reg_c = {0};
    Reg32 reg_d = {0};
    Reg32 reg32_ac_bd = {0};
    Reg32 reg32_bc_ad = {0};

    FloatBs fbs_a, fbs_b, fbs_c, fbs_d, fbs_ac, fbs_bd, fbs_bc, fbs_ad, fbs_tmp1, fbs_tmp2, fbs_ac_bd, fbs_bc_ad;

    reg_a.f = opt1->f[0];
    reg_b.f = opt1->f[1];
    reg_c.f = opt2->f[0];
    reg_d.f = opt2->f[1];

    if (!handle_special_data_fmulc(reg_a.sword, reg_b.sword, reg_c.sword, reg_d.sword, reg32_ac_bd.sword, reg32_bc_ad.sword))
    {
        // 提取符号
        fbs_a.s = reg_a.sword >> 31;
        fbs_b.s = reg_b.sword >> 31;
        fbs_c.s = reg_c.sword >> 31;
        fbs_d.s = reg_d.sword >> 31;

        // 提取指数
        fbs_a.e = ((reg_a.sword >> 23) & 0xFF);
        fbs_b.e = ((reg_b.sword >> 23) & 0xFF);
        fbs_c.e = ((reg_c.sword >> 23) & 0xFF);
        fbs_d.e = ((reg_d.sword >> 23) & 0xFF);

        // 提取尾数 规格化的加上整数1, 非规格化左移1位(规格化和非规格化指数统一参照到127)
        fbs_a.m = (0 != fbs_a.e) ? ((reg_a.sword & 0x7FFFFF) + 0x800000) : ((reg_a.sword & 0x7FFFFF) << 1);
        fbs_b.m = (0 != fbs_b.e) ? ((reg_b.sword & 0x7FFFFF) + 0x800000) : ((reg_b.sword & 0x7FFFFF) << 1);
        fbs_c.m = (0 != fbs_c.e) ? ((reg_c.sword & 0x7FFFFF) + 0x800000) : ((reg_c.sword & 0x7FFFFF) << 1);
        fbs_d.m = (0 != fbs_d.e) ? ((reg_d.sword & 0x7FFFFF) + 0x800000) : ((reg_d.sword & 0x7FFFFF) << 1);

        // 浮点乘法 符号计算
        fbs_ac.s = fbs_a.s ^ fbs_c.s;
        fbs_bd.s = fbs_b.s ^ fbs_d.s;
        fbs_bc.s = fbs_b.s ^ fbs_c.s;
        fbs_ad.s = fbs_a.s ^ fbs_d.s;

        char sign_ac = fbs_ac.s ? (-1) : (1);
        char sign_bd = fbs_bd.s ? (-1) : (1);
        char sign_bc = fbs_bc.s ? (-1) : (1);
        char sign_ad = fbs_ad.s ? (-1) : (1);

        // 指数计算
        fbs_ac.e = fbs_a.e + fbs_c.e;
        fbs_bd.e = fbs_b.e + fbs_d.e;
        fbs_bc.e = fbs_b.e + fbs_c.e;
        fbs_ad.e = fbs_a.e + fbs_d.e;

        // 尾数计算
        fbs_ac.m = fbs_a.m * fbs_c.m;
        fbs_bd.m = fbs_b.m * fbs_d.m;
        fbs_bc.m = fbs_b.m * fbs_c.m;
        fbs_ad.m = fbs_a.m * fbs_d.m;

        int shift = 0;

        if (0x0 == fbs_ac.m && -1 == sign_ac && 1 == sign_bd && 0x0 == fbs_bd.m) // f_0_n - f_n
            reg32_ac_bd.sword = f_0_n;
        else
        {
            shift = fbs_ac.e < fbs_bd.e ? (fbs_bd.e - fbs_ac.e) : (fbs_ac.e - fbs_bd.e);
            fbs_ac_bd.e = fbs_ac.e < fbs_bd.e ? fbs_bd.e : fbs_ac.e;
            fbs_tmp1.m = fbs_ac.e < fbs_bd.e ? ((47 < shift) ? (0x0) : floor((sign_ac * fbs_ac.m) / pow(2, shift))) : ((47 < shift) ? (0x0) : floor(((-sign_bd) * fbs_bd.m) / pow(2, shift)));
            fbs_ac_bd.m = fbs_ac.e < fbs_bd.e ? (fbs_tmp1.m + (-sign_bd) * fbs_bd.m) : (sign_ac * fbs_ac.m + fbs_tmp1.m);

            reg32_ac_bd.f = fbs_ac_bd.m * pow(2, fbs_ac_bd.e - 127 * 2 - 46);
            if ((0 < reg32_ac_bd.f && reg32_ac_bd.f < hex_conv_f(f_min_normal)) || (reg32_ac_bd.f < 0 && hex_conv_f(f_min_normal_n) < reg32_ac_bd.f)) // 非规格化数直接置零,保留符号
            {
                reg32_ac_bd.sword = (0 < reg32_ac_bd.f) ? (f_0) : (f_0_n);
            }
        }
        if (0x0 == fbs_bc.m && -1 == sign_bc && -1 == sign_ad && 0x0 == fbs_ad.m) // f_0_n - f_n
            reg32_bc_ad.sword = f_0_n;
        else
        {
            shift = fbs_bc.e < fbs_ad.e ? (fbs_ad.e - fbs_bc.e) : (fbs_bc.e - fbs_ad.e);
            fbs_bc_ad.e = fbs_bc.e < fbs_ad.e ? fbs_ad.e : fbs_bc.e;
            fbs_tmp2.m = fbs_bc.e < fbs_ad.e ? ((47 < shift) ? (0x0) : floor((sign_bc * fbs_bc.m) / pow(2, shift))) : ((47 < shift) ? (0x0) : floor((sign_ad * fbs_ad.m) / pow(2, shift)));
            fbs_bc_ad.m = fbs_bc.e < fbs_ad.e ? (fbs_tmp2.m + sign_ad * fbs_ad.m) : (sign_bc * fbs_bc.m + fbs_tmp2.m);

            reg32_bc_ad.f = fbs_bc_ad.m * pow(2, fbs_bc_ad.e - 127 * 2 - 46);
            if ((0 < reg32_bc_ad.f && reg32_bc_ad.f < hex_conv_f(f_min_normal)) || (reg32_bc_ad.f < 0 && hex_conv_f(f_min_normal_n) < reg32_bc_ad.f))
            {
                reg32_bc_ad.sword = (0 < reg32_bc_ad.f) ? (f_0) : (f_0_n);
            }
        }
    }

    dst->sword[0] = reg32_ac_bd.sword;
    dst->sword[1] = reg32_bc_ad.sword;

    return true;
}

bool arith_op_cvt64_32(Reg32 *dst, Reg64 *opt1)
{
    double tmp = round(opt1->sdword / pow(2, 32));
    if (tmp < INT32_MIN)
        dst->sword = INT32_MIN;
    else if (tmp > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = round(tmp);
    return true;
}

bool arith_op_i32tof32(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    dst->f = opt1->sword / pow(2, 31 - opt2->word);
    return true;
}

bool arith_op_f32toi32(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (is_nan(opt1->word) || is_inf(opt1->word))
        dst->sword = (GET_BIT(opt1->word, 31)) ? INT32_MIN : INT32_MAX;
    else if (is_zero(opt1->word))
        dst->word = f_0;
    else
    {
        S8 s = CHECK_BIT(opt1->word, 31) ? (-1) : (1);
        double tmp = fabs(opt1->f) * pow(2, 31 - opt2->word);
        if (s * tmp < INT32_MIN)
            dst->sword = INT32_MIN;
        else if (s * tmp > INT32_MAX)
            dst->sword = INT32_MAX;
        else
            dst->sword = s * floor(tmp);
    }
    return true;
}

bool arith_op_relu(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    if (opt1->sword <= 0)
    {
        dst->sword = 0;
    }
    else
    {
        int tmp = 0;
        if (opt2->sword < 15)
            tmp = opt1->sword >> opt2->sword; // 右移指定位
        else if (15 == opt2->sword)
            tmp = opt1->sword >> 16; // 操作数等于15,U31实际移动16位
        else
        {
            printf("opt2 value is invalid! %d\n", opt2->word);
            return false;
        }
        if (tmp > (int)0x00007fff)
        {
            dst->sword = 0x7fff;
        }
        else
        {
            dst->sword = tmp;
        }
    }
    return true;
}

bool arith_op_linear(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    int tmp = 0;
    if (opt2->sword < 15)
        tmp = opt1->sword >> opt2->sword; // 右移指定位
    else if (15 == opt2->sword)
        tmp = opt1->sword >> 16; // 操作数等于15,U31实际移动16位
    else
    {
        printf("opt2 value is invalid! %d\n", opt2->word);
        return false;
    }
    if (tmp > (int)0x00007fff)
    {
        dst->sword = 0x7fff;
    }
    else if (tmp < (int)0xffff8000)
    {
        dst->sword = 0x8000;
    }
    else
    {
        dst->sword = tmp;
    }
    return true;
}

bool arith_op_leaky(Reg32 *dst, Reg32 *opt1, Reg32 *opt2)
{
    int tmp = 0;
    if (opt1->sword < 0)
    {
        tmp = opt1->sword >> 4;
    }
    else
    {
        tmp = opt1->sword;
    }
    if (opt2->sword < 15)
        tmp = tmp >> opt2->sword; // 右移指定位
    else if (15 == opt2->sword)
        tmp = tmp >> 16; // 操作数等于15,U31实际移动16位
    else
    {
        printf("opt2 value is invalid! %d\n", opt2->word);
        return false;
    }
    if (tmp > (int)0x00007fff)
    {
        dst->sword = 0x7fff;
    }
    else if (tmp < (int)0xffff8000)
    {
        dst->sword = 0x8000;
    }
    else
    {
        dst->sword = tmp;
    }
    return true;
}

/**
 * 功能:实现定点数的正弦计算
 * opt1:为归化到[-1, 1]之间的m8p24格式的定点数
 * dst:为m1p31格式的定点数
 */
bool arith_op_sin(Reg32 *dst, Reg32 *opt1)
{
    static int32_t cnt3 = 0;
    int8_t sin_s = GET_BIT(opt1->sword, 31) ? (-1) : (1);
    int64_t norm = opt1->sword;         // m8p24
    int64_t sin_din = norm * pow(2, 6); // m2p30

    /**----------------------------------------------------------*/
    int64_t si = sin_din >> 23; //
    int64_t ci = si + 64;

    int64_t data5 = (sin_din * PI_PAR1) >> 29;          //
    int64_t data0 = ((si * (1 << 23)) * PI_PAR2) >> 29; //

    int64_t d = data5 - data0; //

    int32_t si_adr = si & 255;
    int32_t ci_adr = ci & 255;

    int64_t si_rom = sin_par[si_adr];
    int64_t ci_rom = sin_par[ci_adr];

    int64_t data1 = (si_rom * d) >> 30; //

    int64_t data2 = ci_rom * 2 - data1; //

    int64_t data6 = data2 >> 2; //

    int64_t data3 = (data6 * d) >> 29; //

    double data4 = static_cast<double>(data3);

    int64_t out = si_rom + data4; // m2p30

    int64_t ret = out * 2; // m1p31
    /**----------------------------------------------------------*/
    // m1p31 只有符号位,没有整数位,表示不了sin(pi/2) = 1或者sin(pi/2) = -1, 所以置成极值
    if (ret > INT32_MAX)
        dst->sword = INT32_MAX;
    else if (ret < INT32_MIN)
        dst->sword = INT32_MIN;
    else
        dst->sword = ret;

    // printf("%d\topt1=0x%08x %f dst=0x%08x %f norm=%lld sin_din=%lld ret=%lld\n",
    //        cnt3++, opt1->sword, opt1->sword / pow(2, 24), dst->sword, dst->sword / pow(2, 31), norm, sin_din, ret);
    // printf("-------------------------------------------\n");

    return true;
}

bool arith_op_cos(Reg32 *dst, Reg32 *opt1)
{
    static int32_t cnt2 = 0;
    int8_t sin_s = GET_BIT(opt1->sword, 31) ? (-1) : (1);
    int64_t norm = opt1->sword + 0.5 * pow(2, 24); // +M_PI/2 -> m8p24

    // 再一次归到[-1,1] -> [-2^24, 2^24]
    if (norm > pow(2, 24))
    {
        norm = norm - 2 * pow(2, 24); // sin(alpha) = sin(alpha - 2_PI)
    }

    int64_t sin_din = norm * pow(2, 6); // m2p30

    /**----------------------------------------------------------*/
    int64_t si = sin_din >> 23; // p7 移除23位小数(只剩整数部分)
    int64_t ci = si + 64;

    int64_t data5 = (sin_din * PI_PAR1) >> 29;          // p30  (整数+小数)*PI
    int64_t data0 = ((si * (1 << 23)) * PI_PAR2) >> 29; // p30  整数部分*PI

    int64_t d = data5 - data0; //   p30 小数*PI

    int32_t si_adr = si & 255;
    int32_t ci_adr = ci & 255;

    int64_t si_rom = sin_par[si_adr];
    int64_t ci_rom = sin_par[ci_adr];

    int64_t data1 = (si_rom * d) >> 30; // 浮点数

    int64_t data2 = ci_rom * 2 - data1; //

    int64_t data6 = data2 >> 2; //

    int64_t data3 = (data6 * d) >> 29; //

    double data4 = static_cast<double>(data3);

    int64_t out = si_rom + data4; // m2p30

    int64_t ret = out * 2; // m1p31
    /**----------------------------------------------------------*/
    // m1p31 只有符号位,没有整数位,表示不了cos(0) = 1或者cos(pi) = -1或者或者cos(-pi) = -1, 所以置成极值
    if (ret > INT32_MAX)
        dst->sword = INT32_MAX;
    else if (ret < INT32_MIN)
        dst->sword = INT32_MIN;
    else
        dst->sword = ret;

    // printf("%d\topt1=0x%08x %f dst=0x%08x %f sin_s=%d norm=%lld sin_din=%lld data5=%lld data0=%lld d=%lld si_adr=%d si_rom=%lld ci_adr=%d ci_rom=%lld data1=%lld data2=%lld data6=%lld data3=%lld data4=%llf out=%lld\n",
    //        cnt2++, opt1->sword, opt1->sword / pow(2, 24), dst->sword, dst->sword / pow(2, 31), sin_s, norm, sin_din, data5, data0, d, si_adr, si_rom, ci_adr, ci_rom, data1, data2, data6, data3, data4, out);
    // printf("-------------------------------------------\n");
    return true;
}

bool arith_op_fsin(Reg32 *dst, Reg32 *opt1)
{
    static int32_t cnt = 0;
    double x = opt1->f;
    // 处理异常值
    if (x < -pow(2, 23))
    {
        dst->word = f_qnan;
        return true;
    }
    if (pow(2, 23) < x)
    {
        dst->word = f_qnan;
        return true;
    }
    // 归到[-1, 1]
    while (x > 1)
        x -= 2;
    while (x < -1)
        x += 2;

    int8_t s = (x < 0) ? (-1) : (1);
    x = s * floor((abs(x) * pow(2, 23))) * pow(2, 7); // m2p30
    int64_t dat_sin = (int64_t)x;

    int8_t sin_s = 1;
    int64_t sin_din = 0;
    if (dat_sin < 0)
    {
        sin_din = dat_sin + pow(2, 31);
        sin_s = -1;
    }
    else
    {
        sin_din = dat_sin;
        sin_s = 1;
    }

    /**----------------------------------------------------------*/
    int64_t si = sin_din >> 23; //
    int64_t ci = si + 64;

    int64_t data5 = (sin_din * PI_PAR1) >> 29;          //
    int64_t data0 = ((si * (1 << 23)) * PI_PAR2) >> 29; //

    int64_t d = data5 - data0; //

    int32_t si_adr = si & 255;
    int32_t ci_adr = ci & 255;

    int64_t si_rom = sin_par[si_adr];
    int64_t ci_rom = sin_par[ci_adr];

    int64_t data1 = (si_rom * d) >> 30; //

    int64_t data2 = ci_rom * 2 - data1; //

    int64_t data6 = data2 >> 2; //

    int32_t data3 = (data6 * d) >> 29; //

    double data4 = static_cast<double>(data3);

    int64_t out = si_rom + data4; // m2p30
    int64_t ret = out * 2;        // m1p31
    /**----------------------------------------------------------*/

    dst->f = sin_s * abs(ret) / pow(2, 31);

    // printf("%d\topt1=0x%08x %f dst=0x%08x %f sin_s=%d data5=%lld data0=%lld d=%lld si_adr=%d si_rom=%lld ci_adr=%d ci_rom=%lld data1=%lld data2=%lld data6=%lld data3=%lld data4=%llf out=%lld\n",
    //        cnt++, opt1->word, opt1->f, dst->word, dst->f, sin_s, data5, data0, d, si_adr, si_rom, ci_adr, ci_rom, data1, data2, data6, data3, data4, out);
    // printf("-------------------------------------------\n");
    return true;
}
bool arith_op_fcos(Reg32 *dst, Reg32 *opt1)
{
    static int32_t cnt1 = 0;
    double x = opt1->f;
    // 处理异常值
    if (x < -pow(2, 23))
    {
        dst->word = f_qnan;
        return true;
    }
    if (pow(2, 23) < x)
    {
        dst->word = f_qnan;
        return true;
    }
    // 归到[-1, 1]
    while (x > 1)
        x -= 2;
    while (x < -1)
        x += 2;

    int8_t s = (x < 0) ? (-1) : (1);
    x = s * floor((abs(x) * pow(2, 23))) * pow(2, 7); // m2p30
    int64_t dat_cos = (int64_t)x + 0.5 * pow(2, 30);  // cos(alpha) = sin(PI/2+alpha)
    // 再一次归到[-1,1] -> [-2^30, 2^30]
    if (dat_cos > pow(2, 30))
    {
        dat_cos = dat_cos - 2 * pow(2, 30); // sin(alpha) = sin(alpha - 2_PI)
    }
    int8_t cos_s = 1;
    int64_t cos_din = 0;
    if (dat_cos < 0)
    {
        cos_din = dat_cos + pow(2, 31);
        cos_s = -1;
    }
    else
    {
        cos_din = dat_cos;
        cos_s = 1;
    }

    /**----------------------------------------------------------*/
    int64_t si = cos_din >> 23; // p0
    int64_t ci = si + 64;

    int64_t data5 = (cos_din * PI_PAR1) >> 29;          // m2p30
    int64_t data0 = ((si * (1 << 23)) * PI_PAR2) >> 29; // m2p30

    int64_t d = data5 - data0; // m2p30

    int32_t si_adr = si & 255;
    int32_t ci_adr = ci & 255;

    int64_t si_rom = sin_par[si_adr];
    int64_t ci_rom = sin_par[ci_adr];

    int64_t data1 = (si_rom * d) >> 30; // m1p31

    int64_t data2 = ci_rom * 2 - data1; // m1p31

    int64_t data6 = data2 >> 2; // m3p29

    int32_t data3 = (data6 * d) >> 29; // m2p30

    double data4 = static_cast<double>(data3);

    int64_t out = si_rom + data4; // m2p30

    int64_t ret = out * 2;
    /**----------------------------------------------------------*/

    dst->f = cos_s * abs(ret) / pow(2, 31);

    // printf("%d\topt1=0x%08x %f dst=0x%08x %f cos_s=%d data5=%lld data0=%lld d=%lld si_adr=%d si_rom=%lld ci_adr=%d ci_rom=%lld data1=%lld data2=%lld data6=%lld data3=%lld data4=%llf out=%lld\n",
    //        cnt1++, opt1->word, opt1->f, dst->word, dst->f, cos_s, data5, data0, d, si_adr, si_rom, ci_adr, ci_rom, data1, data2, data6, data3, data4, out);
    // printf("-------------------------------------------\n");
    return true;
}
bool arith_op_fcos1(Reg32 *dst, Reg32 *opt1)
{
    static int32_t cnt1 = 0;
    double x = opt1->f;

    // 处理异常值
    if (x <= -pow(2, 23))
    {
        dst->f = f_qnan;
        return true;
    }
    if (pow(2, 23) <= x)
    {
        dst->f = f_qnan;
        return true;
    }

    x = floor(x * pow(2, 23)); // m2p23浮点23位小数,转成整数
    // 归到[-1, 1] -> [-2^23, 2^23]
    while (x > pow(2, 23))
        x -= 2 * pow(2, 23);
    while (x < -pow(2, 23))
        x += 2 * pow(2, 23);

    x *= 2;                       // 转成m8p24
    x += floor(0.5 * pow(2, 24)); // cos(alpha) = sin(alpha + PI/2)
    // 再一次归到[-1,1] -> [-2^24, 2^24]
    while (x > pow(2, 24))
        x -= 2 * pow(2, 24);

    int64_t cos_din = (int64_t)x * pow(2, 6); // 转到m2p30

    /**----------------------------------------------------------*/
    int64_t si = cos_din >> 23; //
    int64_t ci = si + 64;

    int64_t data5 = (cos_din * PI_PAR1) >> 29;          // m2p30
    int64_t data0 = ((si * (1 << 23)) * PI_PAR2) >> 29; // m2p30

    int64_t d = data5 - data0; // m2p30

    int32_t si_adr = si & 255;
    int32_t ci_adr = ci & 255;

    int64_t si_rom = sin_par[si_adr];
    int64_t ci_rom = sin_par[ci_adr];

    int64_t data1 = (si_rom * d) >> 30; // m1p31

    int64_t data2 = ci_rom * 2 - data1; // m1p31

    int64_t data6 = data2 >> 2; // m3p29

    int32_t data3 = (data6 * d) >> 29; // m2p30

    double data4 = static_cast<double>(data3);

    int64_t out = si_rom + data4; // m2p30

    int64_t ret = out * 2;
    /**----------------------------------------------------------*/
    double tmp = (double)(ret) / pow(2, 31);
    dst->f = out / pow(2, 30);
    // printf("%d\topt1=0x%08x %f dst=0x%08x %f tmp=%llf data5=%lld data0=%lld d=%lld si_adr=%d si_rom=%lld ci_adr=%d ci_rom=%lld data1=%lld data2=%lld data6=%lld data3=%lld data4=%llf out=%lld\n",
    //        cnt1++, opt1->word, opt1->f, dst->word, dst->f, tmp, data5, data0, d, si_adr, si_rom, ci_adr, ci_rom, data1, data2, data6, data3, data4, out);
    // printf("-------------------------------------------\n");
    return true;
}
bool arith_op_log2_m16p16(Reg32 *dst, Reg32 *opt1)
{
    // S16 integer = opt1->shword[1];                                          // 从高16位取出整数部分(包括符号位)
    // float decimal = opt1->shword[0] / pow(2, 16);                           // 从低16位取出小数部分
    // float frac = (integer < 0) ? (integer - decimal) : (integer + decimal); // 得到真实的浮点数

    // if (frac <= 0)
    //     dst->word = f_0_n;
    // else
    // {
    //     double a = log2(frac) * pow(2, 24);
    //     dst->sword = round(a);
    // }
    if (GET_BIT(opt1->sword, 31))
        dst->sword = INT32_MIN;
    else
    {
        double tmp = log2(opt1->sword / pow(2, 15));
        dst->sword = tmp * pow(2, 23);
    }
    return true;
}

bool arith_op_log2_frac32(Reg32 *dst, Reg32 *opt1)
{
    float decimal = (opt1->sword & 0x7FFFFFFF) / pow(2, 31);
    S8 integer = CHECK_BIT(opt1->sword, 31) ? (-1) : (0);
    float frac = (integer < 0) ? (integer - decimal) : (integer + decimal);
    if (frac <= 0)
        dst->word = f_0_n;
    else
    {
        double a = log2(frac) * pow(2, 24);
        dst->sword = round(a);
    }
    return true;
}
bool arith_op_exp2_m16p16(Reg32 *dst, Reg32 *opt1)
{
    static int32_t cnt = 0;
    /**
     * m16p16数据格式就要求输入的浮点数在-16~15之间，否则2的指数后转成m16p16就表达不了(2^15*2^16=2^31),
     * 这样就要求输入的m8p24必须在-16*2^24~15*2^24之间
     */
    if (opt1->sword <= -16 * pow(2, 24))
    {
        dst->sword = 1;
        return true;
    }
    if (15 * pow(2, 24) <= opt1->sword)
    {
        dst->sword = INT32_MAX;
        return true;
    }
    int32_t x = opt1->sword;
    double ret = 0.0;
    int8_t integer = x >> 24;             // 取m8p24格式的整数部分
    int32_t remain_bin = x & 0xffffff;    // 取m8p24格式的小数部分二进制对应的10进制数
    int32_t index = (x & 0xf80000) >> 19; // 取m8p24格式的小数部分前5个二进制数对应的10进制数
    int64_t dat_integer, dat_remain, mul_dat;

    if (0x000000 != remain_bin) // 判断是不是整数
    {
        if (CHECK_BIT(x, 31)) // 判断符号
        {
            dat_integer = static_cast<int64_t>(std::floor(pow(2, integer) * pow(2, 16)));                           // p16  因为输入浮点数小于-16,但取出来的integer最小就可以等于-16,此处乘以2^16是保留整数精度
            dat_remain = exp_lut[index];                                                                            // p14
            mul_dat = static_cast<int64_t>(std::floor(static_cast<double>(dat_integer) * dat_remain / pow(2, 14))); // p16
        }
        else
        {
            dat_integer = static_cast<int64_t>(std::floor(pow(2, integer) * pow(2, 2))); // p2  此处乘以2^2,并不是为了保留精度,因为正数不需要,只是为了与小数一起凑成p16
            dat_remain = exp_lut[index];                                                 // p14
            mul_dat = static_cast<int64_t>(std::floor(static_cast<double>(dat_integer) * dat_remain));
        }
        ret = mul_dat;
    }
    else
    {
        ret = pow(2, integer) * pow(2, 16);
    }
    // printf("\tinteger=%d remain_bin=0x%08x index=%d dat_integer=%ld dat_remain=%ld mul_dat=%d ret=%lf\n", integer, remain_bin, index, dat_integer, dat_remain, mul_dat, ret);

    if (ret > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = ret; // m16p16

    // printf("%d\topt1=0x%08x %f dst=0x%08x %f correct=0x%08x %f ret=%llf\n", cnt++, opt1->sword, opt1->sword / pow(2, 24), dst->sword, dst->sword / pow(2, 16), pow(2, opt1->sword / pow(2, 24)) * pow(2, 16), pow(2, opt1->sword / pow(2, 24)), ret);
    // printf("-------------------------------\n");
    return true;
}

bool arith_op_exp2_frac32(Reg32 *dst, Reg32 *opt1)
{
    static int32_t cnt = 0;
    /**
     * frac32数据格式就要求输入的浮点数在小于0，否则2的指数后转成frac32就表达不了(2^31),
     * 这样就要求输入的m8p24必须在-31*2^24~0*2^24之间
     */
    if (opt1->sword <= -31 * pow(2, 24))
    {
        dst->sword = 1;
        return true;
    }
    if (0 <= opt1->sword)
    {
        dst->sword = INT32_MAX;
        return true;
    }
    double ret = 0.0;
    int32_t x = opt1->sword;
    int8_t integer = x >> 24;             // 取m8p24格式的整数部分
    int32_t remain_bin = x & 0xffffff;    // 取m8p24格式的小数部分二进制对应的10进制数
    int32_t index = (x & 0xf80000) >> 19; // 取m8p24格式的小数部分前5个二进制数对应的10进制数
    int64_t dat_integer, dat_remain, mul_dat;

    if (0x000000 != remain_bin) // 判断是不是整数
    {
        if (CHECK_BIT(x, 31)) // 判断符号
        {
            dat_integer = static_cast<int64_t>(std::floor(pow(2, integer) * pow(2, 31)));                           // p31 因为输入浮点数小于-31,但取出来的integer最小就可以等于-31,此处乘以2^32是保留整数精度
            dat_remain = exp_lut[index];                                                                            // p14
            mul_dat = static_cast<int64_t>(std::floor(static_cast<double>(dat_integer) * dat_remain / pow(2, 14))); // p31
        }
        ret = mul_dat;
    }
    else
    {
        ret = pow(2, integer) * pow(2, 31);
    }
    // printf("\tinteger=%d remain_bin=0x%08x index=%d dat_integer=%ld dat_remain=%ld mul_dat=%d ret=%lf\n", integer, remain_bin, index, dat_integer, dat_remain, mul_dat, ret);

    if (ret > INT32_MAX)
        dst->sword = INT32_MAX;
    else
        dst->sword = ret;

    // printf("%d\topt1=0x%08x %f dst=0x%08x %f correct=0x%08x %f ret=%llf\n", cnt++, opt1->sword, opt1->sword / pow(2, 24), dst->sword, dst->sword / pow(2, 31), pow(2, opt1->sword / pow(2, 24)) * pow(2, 16), pow(2, opt1->sword / pow(2, 24)), ret);
    // printf("-------------------------------\n");
    return true;
}
